package com.iqcctt.businessprocess.utils;

import com.iqcctt.businessprocess.annotation.BPE;
import com.iqcctt.businessprocess.annotation.BusinessProcess;
import com.iqcctt.businessprocess.execption.BusinessProcessException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 〈一句话功能简述〉<br>
 * 〈加载流程〉
 *
 * @author TLVM
 * @create 3/24/2024
 * @since 1.0.0
 */
public class BusBindUtils {

    public static <IQCCTT> void bind(IQCCTT iqcctt) throws Exception {
        bind(Stream.of(iqcctt).collect(Collectors.toList()));
    }

    public static <IQCCTT> void bind(List<IQCCTT> iqcctt) throws Exception {
        for (Object result : iqcctt) {
            Class<?> cls = result.getClass();
            Annotation[] clsAnnotations = cls.getAnnotations();
            for (Annotation annotation : clsAnnotations) {
                if (annotation.annotationType().isAssignableFrom(BusinessProcess.class)) {
                    annoFlow(result,annotation);
                }
            }
        }
    }

    /*
     * @Author LiTao
     * @Description 校验注解流程
     * @Date 2:03 PM 3/25/2024
     * @Param
     * @return
     **/
    private static void annoFlow(Object result, Annotation annotation) throws Exception {
        BusinessProcess businessProcess = (BusinessProcess) annotation;
        BPE[] bpes = businessProcess.BPE();
        for (BPE bpe : bpes) {
            //组装参数列表
            VerifyUtils.verifyFieldLen(result,bpe);
            if(VerifyUtils.verifyContinue(result,bpe))continue;
            // 使用反射加载类
            exeBeanMethod(result,bpe);
        }
    }

    /*
     * @Author LiTao
     * @Description 通过反射执行方法
     * @Date 2:02 PM 3/25/2024
     * @Param
     * @param result 实体bean
     * @param bpe 注解参数
     * @return
     **/
    private static void exeBeanMethod(Object result, BPE bpe) throws Exception {
        try{
            Class<?> clazz = Class.forName(bpe.exeCls());
            //加载方法参数
            Object[] argsList = loadParamVal(result, bpe);
            for (Method method : clazz.getDeclaredMethods()) {
                if(method.getName().equals(bpe.exeMethod())&&method.getParameterTypes().length==argsList.length){
                    //参数名称及参数长度一致
                    boolean isMatch = true;
                    //校验参数类型是否一致
                    for (int i = 0; i < argsList.length; i++) {
                        if (!method.getParameterTypes()[i].isInstance(argsList[i])) {
                            isMatch = false;
                            break;
                        }
                    }
                    if (isMatch) {
                        // 创建实例
                        Object instance = clazz.newInstance();
                        // 执行方法
                        method.invoke(instance, argsList);
                        break;
                    }
                }
            }
        }catch (ClassNotFoundException e){
            throw new BusinessProcessException("找不到类路径:"+bpe.exeCls());
        }
    }

    /*
     * @Author LiTao
     * @Description 加载方法参数
     * @Date 3:36 PM 3/25/2024
     * @Param
     * @return
     **/
    private static Object[] loadParamVal(Object result, BPE bpe){
        Object[] argsList = new Object[bpe.paramVal().length];
        for (int i = 0; i < bpe.paramVal().length; i++) {
            argsList[i]= getValue(result, bpe.paramVal()[i]);
        }
        return argsList;
    }

    public static Object getValue(Object object, String fieldName) {
        try {

            Field field = object.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(object);
        } catch (NoSuchFieldException e) {

        } catch (IllegalAccessException e) {

        }
        return null;
    }


}
